#!/bin/bash
#author: xieziqiang
#email: xie.zi.qiang@outlook.com

set -e
#****** vars *********#
REDIS_VERSION="7.2.5"
REDIS_PASSWORD="123456"
REDIS_USER="redis"
REDIS_INSTALL_PATH="/usr/local/redis"
REDIS_SRC_PATH="/usr/local/src"

#****** functions *********#
color() {
    local message="$1"
    local status="$2"
    local terminal_width
    terminal_width=$(tput cols)
    local middle_column=$(( terminal_width / 2))
    local SETCOLOR_SUCCESS="\033[1;32m"  # 绿色
    local SETCOLOR_FAILURE="\033[1;31m"  # 红色
    local SETCOLOR_WARNING="\033[1;33m"  # 黄色
    local SETCOLOR_NORMAL="\033[0m"      # 重置颜色
    printf '%s\n\033[%sG' "${message}"  "${middle_column}"
    # Print the status message
    printf "["
    case ${status} in
        success|0)
            echo -en  "${SETCOLOR_SUCCESS}  OK  "
            ;;
        failure|1)
            echo -en  "${SETCOLOR_FAILURE}FAILED"
            ;;
        *)
            echo -en "${SETCOLOR_WARNING}WARNING"
            ;;
    esac
    echo -e "${SETCOLOR_NORMAL}]"
}

judge_current_user () {
    if [ "$(id -u)" = "0" ];then
        color "current user is administrator" 0
    else
        color "current user is not administrator" 1
        exit
    fi
}

create_dir () {
    local i
    for i in "$@";do
        if [ ! -d "$i" ];then
            mkdir -pv "$i" && color "$i dir is created" 0
        else
            color "$i dir is existed." 2
        fi
    done
}

create_user () {
    if ! id "$1" &> /dev/null;then
        useradd -r -s /sbin/nologin  -M "$1" \
        && color "$1 user is created." 0 \
        || { color "$1 user create failed.";exit; }
    else
        color "$1 user is existed." 2
    fi
}

process_file () {
    if [ ! -e "redis-${REDIS_VERSION}.tar.gz" ];then
        color "current directory dont exist redis-${REDIS_VERSION}.tar.gz" 1
        exit
    else
        tar -xvf "redis-${REDIS_VERSION}.tar.gz" -C "${REDIS_SRC_PATH}"
    fi
} 

compile_redis () {
    create_dir ${REDIS_INSTALL_PATH}/{data,etc,log,pid}
    apt update \
    && apt install -y make gcc libsystemd-dev pkg-config
    cd  "${REDIS_SRC_PATH}/redis-${REDIS_VERSION}" || exit
    make  USE_SYSTEMD=yes PREFIX=${REDIS_INSTALL_PATH} install \
    && color "redis compile is finshed." 0 \
    || { color "redis compile is failed.";exit; }
    cd -
}

config_redis_file () {
    sed -i '/vm.overcommit_memory/s/^/#/g' /etc/sysctl.conf
    echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf
    sysctl -p

    cat > /etc/profile.d/redis.sh <<EOF
export PATH=\${PATH}:${REDIS_INSTALL_PATH}/bin
EOF

cat > /lib/systemd/system/redis-server.service <<EOF
[Unit]
Description=Advanced key-value store
After=network.target
Documentation=http://redis.io/documentation, man:redis-server(1)

[Service]
WorkingDirectory=${REDIS_INSTALL_PATH}
Type=notify
ExecStart=${REDIS_INSTALL_PATH}/bin/redis-server ${REDIS_INSTALL_PATH}/etc/redis.conf --supervised systemd --daemonize no
TimeoutStopSec=0
Restart=always

User=${REDIS_USER}
Group=${REDIS_USER}
RuntimeDirectory=redis
RuntimeDirectoryMode=2755

UMask=007
PrivateTmp=yes
LimitNOFILE=65535
PrivateDevices=yes
ProtectHome=yes
ReadOnlyDirectories=/
ReadWritePaths=-${REDIS_INSTALL_PATH}
ReadWritePaths=-${REDIS_INSTALL_PATH}
ReadWritePaths=-${REDIS_INSTALL_PATH}

NoNewPrivileges=true
CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE
MemoryDenyWriteExecute=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictRealtime=true
RestrictNamespaces=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX

# redis-server can write to its own config file when in cluster mode so we
# permit writing there by default. If you are not using this feature, it is
# recommended that you replace the following lines with "ProtectSystem=full".
ProtectSystem=true
ReadWriteDirectories=-${REDIS_INSTALL_PATH}/etc

[Install]
WantedBy=multi-user.target
Alias=redis.service
EOF

    \cp -b ${REDIS_SRC_PATH}/redis-${REDIS_VERSION}/redis.conf ${REDIS_INSTALL_PATH}/etc/

    sed -i -e '/^bind/c bind 0.0.0.0' \
    -e '/^dir/c dir ./data/' \
    -e '/^pidfile/c pidfile ../pid/redis-6379.pid' \
    -e '/^logfile/c logfile ../log/redis-6379.log' \
    -e "/^# requirepass/a requirepass ${REDIS_PASSWORD}" ${REDIS_INSTALL_PATH}/etc/redis.conf
    
}

start_redis () {
    chown -R ${REDIS_USER}:${REDIS_USER} "${REDIS_INSTALL_PATH}"
    systemctl daemon-reload
    systemctl enable redis-server
    systemctl start redis-server \
    && color "start redis-server is success." 0 \
    || { color "start redis-server is failed.";exit; }
}

main () {
    judge_current_user
    create_user ${REDIS_USER}
    process_file
    compile_redis
    config_redis_file
    start_redis
}

main